package com.acme.bankapp.service.bank;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.client.Client;
import com.acme.bankapp.exception.ClientExistsException;
import com.acme.bankapp.exception.DeserializationException;
import com.acme.bankapp.listeners.ClientRegistrationListener;
import com.acme.bankapp.listeners.DebugListener;
import com.acme.bankapp.listeners.EmailNotificationListener;
import com.acme.bankapp.listeners.PrintClientListener;

public class BankService {

    public static final String DEFAULT_FILENAME = "testOut.txt";

    public static BankService loadBank(final File file)
	    throws DeserializationException, IOException {
	BankService bankService = BankDataLoaderService.load(file);
	return bankService;
    }

    public static BankService loadBank(final String fileName)
	    throws DeserializationException, IOException {
	BankService bankService = BankDataLoaderService.load(fileName);
	return bankService;
    }

    private String saveFileName = DEFAULT_FILENAME;
    private List<ClientRegistrationListener> listeners = new LinkedList<>();

    private Bank bank;

    public BankService(final Bank bank) {
	super();
	this.bank = bank;
	PrintClientListener printer = new PrintClientListener();
	EmailNotificationListener mailNotif = new EmailNotificationListener();
	DebugListener debug = new DebugListener();
	listeners.add(printer);
	listeners.add(mailNotif);
	listeners.add(debug);
    }

    public BankService(final Bank bank,
	    final List<ClientRegistrationListener> listeners) {
	super();
	this.bank = bank;
	this.listeners = listeners;
    }

    public void addClient(final Client newClient) throws ClientExistsException,
	    IOException {
	List<Client> clients = getClients();
	if (clients.contains(newClient)) {
	    throw new ClientExistsException("Client already exists!");
	}
	clients.add(newClient);
	callListeners(newClient);
	saveBank();
    }

    public Client getClient(final String clientName) {
	Client result = null;
	List<Client> clients = bank.getClients();
	for (Client client : clients) {
	    if (client.getName().equals(clientName)) {
		result = client;
	    }
	}
	return result;
    }

    public List<Client> getClients() {
	return bank.getClients();
    }

    public String getSaveFileName() {
	return saveFileName;
    }

    public void printBalance() {
	for (Client client : bank.getClients()) {
	    System.out.println(client.toString() + "'s balance: "
		    + client.getAccount().getBalance());
	}
    }

    public void printMaximumAmountToWithdraw() {
	for (Client client : bank.getClients()) {
	    System.out.println(client + "'s max.amount to withdraw: "
		    + client.getAccount().maximumAmountToWithdraw());
	}
    }

    public void saveBank() throws IOException {
	BankDataSaverService.save(this, saveFileName);
    }

    public void saveBank(final File file) throws IOException {
	BankDataSaverService.save(this, file);
    }

    public void saveBank(final String fileName) throws IOException {
	BankDataSaverService.save(this, fileName);
    }

    public void setSaveFileName(final String saveFileName) {
	this.saveFileName = saveFileName;
    }

    private void callListeners(final Client newClient) {
	for (ClientRegistrationListener listener : listeners) {
	    listener.onClientAdded(newClient);
	}
    }
}
